$(function(){	
	get = function(objType, id, action, mode, skipDatasourceCheck) {
		/****************
		action.  default "detail". options: detail, edit
		mode.  default "inline". options: modal, inline
		skipDatasourceCheck.  default false.  causes controller to skip the datasource loaded check.
		****************/
		var action = !action ? "detail" : action;
		var mode = !mode ? "inline" : mode;
		var skipDatasourceCheck = !skipDatasourceCheck ? false : true;
		// check that the datasource for the underlying object has been loaded
		if (!skipDatasourceCheck && !datasourceLoaded(objType)) {
			loadDatasource(objType, function() {
				get(objType, id, action, mode, true);
			});
			return;
		}
		var vm = populateVMFromModel(getViewModel(objType), getModel(objType, id));
		var uiConfig = vm.uiConfig()[action][mode];
		// check to see if content template is in the DOM, load if not
		loadTemplate(uiConfig.contentType, uiConfig.contentTemplate);
		var uiTemplate = kendo.template($("#" + uiConfig.contentTemplate).html(), {useWithBlock: false});
		$("body").append(uiTemplate(uiConfig));
		//$("#" + uiConfig.contentId).hide();
		kendo.bind($("#" + uiConfig.contentId), vm);
		// REFACTOR: switch form post-processing with a contentOnload function in the view model	
		switch (uiConfig.objType) {
			case "workshop":
				switch (uiConfig.contentType) {
					case "form":
						var workshopYear = vm.get("program_year").split("-")[1];
						var workshopDatePicker = $("#" + uiConfig.contentId + " .workshop_date").data("kendoDatePicker");
						workshopDatePicker.min(new Date(workshopYear, 0, 1));
						workshopDatePicker.max(new Date(workshopYear, 2, 2));
						var startTimePicker = $("#" + uiConfig.contentId + " .start_time").data("kendoTimePicker");
						startTimePicker.min(new Date(2000, 10, 10, 8, 0, 0));
						startTimePicker.max(new Date(2000, 10, 10, 23, 30, 0));
						var endTimePicker = $("#" + uiConfig.contentId + " .end_time").data("kendoTimePicker");
						endTimePicker.min(new Date(2000, 10, 10, 8, 0, 0));
						endTimePicker.max(new Date(2000, 10, 10, 23, 30, 0));
						loadTemplate("form", "offlineReasonsFormTemplate");
						var orTemplate = kendo.template($("#offlineReasonsFormTemplate").html(), {useWithBlock: false});
						var orConfig = {};
						orConfig.contentId = "offlineReasonsForm";
						orConfig.data = vm.get("offlineReasons");
						//$("body").append(orTemplate(orConfig));
						$("#offlineReasonsPopover").popover({
							trigger: "manual",
							placement: "right",
							html: true,
							title: "Why won't your workshop offer computer access?",
							content: orTemplate(orConfig)
						});
						$("#startTimePopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "Start Time",
							content: "Workshops scheduled <strong>during the week</strong> should begin after noon.  Please consider parent travel time from work when scheduling your workshop."
						});
						$("#endTimePopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "End Time",
							content: "Workshops should be scheduled to end no later than 9:30 PM",
						});
						$("#siteContactPopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "Site Contact",
							content: "Person responsible at your site and whose number and email will be listed as the contact in the workshop locator on the Cal Grant website"
						});
						$("#organizerPopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "Organizer",
							content: "Person accountable to register workshop, order materials, request site support funds"
						});
						$("#anticipatedStudentsPopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "Anticipated Students",
							content: "If you cannot serve at least 25 students, please reconsider registering this workshop. Contact your regional or statewide office at cashforcollege@csac.ca.gov"
						});
						$("#anticipatedComputersPopover").popover({
							trigger: "hover",
							placement: "right",
							html: true,
							title: "Anticipated Computers",
							content: "Workshops that do not offer computer access will require special authorization"
						});
						/*$("#startTimeTooltip").tooltip({
							title: "This is the tooltip title from javascript",
							trigger: "hover"	
						});*/
					break;
				}
			break;
			case "workshopVolunteer":
				// read the volunteer into the datasource so it will be available for save, if neccessary
				volunteers.read({volunteer_id: vm.get("volunteer_id")});
				if (uiConfig.id == 0) {
						var nextWorkshopDate = getNextWorkshopDate();
						if (!nextWorkshopDate) {
							$("#noRegisteredWorkshopsPopover").popover("show");
							return;
						}
					}
			break;
			case "order":
				switch (uiConfig.contentType) {
					case "wizard":
						if (uiConfig.id == 0) {
							var nextWorkshopDate = getNextWorkshopDate();
							if (nextWorkshopDate) {
								var anticipatedShipDate = new Date(nextWorkshopDate);
								anticipatedShipDate.setDate(anticipatedShipDate.getDate()-28);
								vm.set("anticipated_ship_date", kendo.toString(anticipatedShipDate, "d"));
							} else {
								$("#noScheduledWorkshopsPopover").popover("show");
								return;
							}
						}
						orderValues.bind("change", function(e) {
							var vm = orderViewModel;
							var csItemMap = genCatSubcatItemMap(e.items);
							//console.log(csItemMap);
							if (e.items.length) {
								loadTemplate("wizard", "wizardStepTemplate");
								var wsTemplate = kendo.template($("#wizardStepTemplate").html(), {useWithBlock: false});
								loadTemplate("form", "orderValuesFormTemplate");
								var ovTemplate = kendo.template($("#orderValuesFormTemplate").html(), {useWithBlock: false});
								var step = $("#" + uiConfig.contentId + " .wizardContainer > .wizardStep").length + 1;
								var ovIds = [];
								$.each(csItemMap, function(index, value) {
									var ovConfig = {};
									ovConfig.contentId = "orderValues" + step;
									ovConfig.title = index;
									ovConfig.data = value;
									$("body").append(ovTemplate(ovConfig));
									var wsConfig = {};
									wsConfig.step = step;
									wsConfig.title = index;
									//wsConfig.columns = 1;
									$("#" + uiConfig.contentId + " .wizardContainer").append(wsTemplate(wsConfig));
									$("#" + ovConfig.contentId).appendTo($("#" + uiConfig.contentId + " .wizardContainer .step" + step));
									$.each(value, function(idx, val) {
										$.each(val, function(i, v) {
											ovIds.push(v.order_value_id);
										})
									});
									step = step + 1;
								});
							};
							var orderValueIds = vm.get("order_value_ids");
							var quantities = vm.get("quantities");
							//console.log(orderValueIds);
							//console.log(quantities);
							var qtys = [];
							$.each(ovIds, function(index, value) {
								var i = $.inArray(value.toString(), orderValueIds);
								//console.log(i);
								i != -1 ? qtys.push(quantities[i]) : qtys.push(0);
							});
							vm.set("order_value_ids", ovIds);
							vm.set("quantities", qtys);
							kendo.bind($("#" + uiConfig.contentId), vm);
							//console.log(vm);
							orderValues.unbind("change");
						});
						orderValues.read();
					break;
				}
			break;
			case "oap":
				switch (uiConfig.contentType) {
					case "wizard":
						oapValues.bind("change", function(e) {
							var vm = oapViewModel;
							var csItemMap = genCatSubcatItemMap(e.items);
							if (e.items.length) {
								loadTemplate("wizard", "wizardStepTemplate");
								var wsTemplate = kendo.template($("#wizardStepTemplate").html(), {useWithBlock: false});
								loadTemplate("form", "oapValuesFormTemplate");
								var oapTemplate = kendo.template($("#oapValuesFormTemplate").html(), {useWithBlock: false});
								var step = $("#" + uiConfig.contentId + " .wizardContainer > .wizardStep").length + 1;
								var oapIds = [];
								$.each(csItemMap, function(index, value) {
									var oapConfig = {};
									oapConfig.contentId = "oapValues" + step;
									oapConfig.title = index;
									oapConfig.subTitle = "Select 2 items from the list.";
									oapConfig.data = value;
									$("body").append(oapTemplate(oapConfig));
									var wsConfig = {};
									wsConfig.step = step;
									wsConfig.title = index;
									//wsConfig.columns = 1;
									$("#" + uiConfig.contentId + " .wizardContainer").append(wsTemplate(wsConfig));
									$("#" + oapConfig.contentId).appendTo($("#" + uiConfig.contentId + " .wizardContainer .step" + step));
									step = step + 1;
								});
							};
							kendo.bind($("#" + uiConfig.contentId), vm);
							oapValues.unbind("change");
						});
						oapValues.read();
					break;
					case "detail":
						oapValues.one("change", function(e) {
							var oapValueIds = vm.get("oap_value_ids");
							//console.log(oapValueIds);
							var csItemMap = genCatSubcatItemMap(e.items);
							$.each(csItemMap, function(index, value) {
								$("#" + uiConfig.contentId).append("<h4>" + index + "</h4>");
								$.each(value, function(idx, val) {
									var subCatShown = false;
									$("#" + uiConfig.contentId).append("<dl>");
									$.each(val, function(i, v) {
										if ($.inArray(v.oap_value_id.toString(), oapValueIds) != -1) {
											if (idx.length > 0 && !subCatShown) {
												$("#" + uiConfig.contentId).append("<dt>" + idx + "</dt>");
												subCatShown = true;
											}
											$("#" + uiConfig.contentId).append("<dd>" + v.description + "</dd>");
										}
									})
									$("#" + uiConfig.contentId).append("</dl>");
								})
							})
						});
						oapValues.read();					
					break;
				}
			break;
		};
		// send to modal or process inline element
		// REFACTOR: set up modalOnload in uiConfig in the view model
		switch (mode) {
			case "modal":
				if (uiConfig.contentType == "form") {
					uiConfig.modalOnload = function() {
						if (uiConfig.id == 0) {
							$("#" + uiConfig.modalId + " .deleteButton").hide();
						}
						if (uiConfig.objType == "user" && uiConfig.id == authUser.userId) {
							$("#" + uiConfig.modalId + " .deleteButton").hide();
						};
						if (uiConfig.objType == "pa") {
							if (uiConfig.id == 0) {
								$("#" + uiConfig.modalId + " .acceptButton").on("click", acceptPA);
								//$("#" + uiConfig.modalId + " .declineButton").on("click", declinePA);
								$("#" + uiConfig.modalId + " .declineButton").hide();
							} else {
								$("#" + uiConfig.modalId + " .acceptButton").text("Close");
								$("#" + uiConfig.modalId + " .acceptButton").on("click", closeModal)
								$("#" + uiConfig.modalId + " .declineButton").hide();
							}
						}
						if (uiConfig.objType == "organization") {
							$("#" + uiConfig.modalId + " .deleteButton").hide();
						};
						if (authUser.role == "Site Contact" && uiConfig.objType != "user") {
							$("#" + uiConfig.modalId + " .saveButton").hide();
							$("#" + uiConfig.modalId + " .deleteButton").hide();
						}
					};
				} else if (uiConfig.contentType == "wizard") {
					uiConfig.modalOnload = function() {
						initWizardModal(vm);
						if (uiConfig.objType == "oap") {
							$("#" + uiConfig.modalId + " .cancelButton").hide();
							$("#" + uiConfig.modalId + " .finishButton").on("click", finishOAP);
						}
					}
				} else if (uiConfig.contentType == "detail") {
					$("#" + uiConfig.modalId + " .closeButton").show();
				}					
				launchModal(uiConfig)
			break;
			case "inline":
				$("#" + uiConfig.contentId).appendTo("#" + uiConfig.inlineId);
			break;	
		};
	};
	save = function(objType, id) {
		// save assumes all datasources have been loaded for any required objTypes
		// validate form
		var validator = $("#" + objType + id + "Form").kendoValidator({messages: validatorMessages}).data("kendoValidator");
		if (validator.validate() == false) {return false};
		// custom validation
		switch (objType) {
			case "user":
				// dupe check email
				var isEmailDupe = false;
				var duplicateEmails = getDuplicateEmails(userViewModel.get("email"));
				if (duplicateEmails.length) {
					$.each(duplicateEmails, function(index, value) {
						if (value.user_id != id && !isEmailDupe) {
							alert("The e-mail address entered is already in the system");
							isEmailDupe = true;
						};							
					});
					if (isEmailDupe) {
						return false;
					};
				}
			break;
		};
		if (objType == "workshopVolunteer") {
			// CHECK THIS!!!!!!!!!
			// need to dupe check volunteer email
			var wvModel = populateModelFromVM(getModel(objType, id), getViewModel("workshopVolunteer"));
			var vModel = populateModelFromVM(getModel("volunteer", model.volunteer_id), getViewModel("workshopVolunteer"));
			if (model.volunteer_id == 0) {
				// this needs to be synchronous
				volunteers.add(vModel);
				volunteers.sync();
				volunteers.read();
				wvModel.volunteer_id = volunteerId;
			}
			if (id == 0) {
				volunteerWorkshops.add(wvModel);
			}
		} else {
			var model = populateModelFromVM(getModel(objType, id), getViewModel(objType, id));
			var datasource = getDatasource(objType);
			if (id == 0) {
				datasource.add(model);
			}
			datasource.sync();
			setTimeout(function() {
				datasource.read();
			}, 800);
		}
		var mode = (modalArray[modalArray.length - 1].objType == objType && modalArray[modalArray.length - 1].id == id) ? "modal" : "inline";
		if (mode == "modal") {
			closeModal();
		}
	};
	confirmDel = function(objType, id) {
		var uiConfig = {};
		uiConfig.objType = objType;
		uiConfig.id = id;
		uiConfig.modalId = objType + id + "ConfirmDelModal";
		uiConfig.modalTemplate = "confirmModalTemplate";
		uiConfig.modalTitle = "Confirm Deletion";
		uiConfig.message = "Are you sure you want to delete this " + objType + "?";
		launchModal(uiConfig);
	};
	del = function(objType, id) {
		var lastModal = modalArray[modalArray.length - 1];
		var nextModal = modalArray[modalArray.length - 2];
		if (typeof lastModal == "object" && lastModal.modalTemplate == "confirmModalTemplate") {
			closeModal();
		}
		var datasource = getDatasource(objType);
		var model = datasource.get(id);
		datasource.remove(model);
		datasource.sync();
		setTimeout(function() {
			datasource.read();
		}, 800);
		if (typeof nextModal == "object" && nextModal.modalTemplate == "formModalTemplate") {
			closeModal();
		};
	};
	datasourceLoaded = function(objType) {
		return getDatasource(objType).total()
	};
	loadDatasource = function(objType, cb) {
		var ds = getDatasource(objType);
		ds.one("change", function() {
			cb();
		});
		ds.read();
	};
	populateVMFromModel = function(vm, model) {
		$.each(vm, function(index, value){
			if (index != "uid") {
				// set all defaults that can't be set in model, convert model data to view model data where necessary (e.g. convert model lists to view model arrays)
				if (index == "oap_value_ids" || index == "offline_reasons" || index == "order_value_ids" || index == "quantities") {
					vm.set(index, model.id == 0 || model[index] == "" ? [] : model[index].split(","));
				} else if (index == "organization_id") {
					vm.set(index, model.id == 0 ? authUser.organizationId : model.organization_id);
				} else if (index == "ordered_by_id") {
					vm.set(index, model.id == 0 ? authUser.userId : model.ordered_by_id);
				} else if (index == "program_year") {
					vm.set("program_year", model.id == 0 ? currentProgramYear : model.program_year);
				} else if (index == "evaluation_code") {
					vm.set("evaluation_code", model.id == 0 ? generateEvaluationCode() : model.evaluation_code);
				} else if (typeof model.fields[index] != "undefined" && model.fields[index].type == "boolean") {
					vm.set(index, model[index] == 1 ? true : false);
				} else if (typeof value != "function" && typeof value != "object" && typeof model[index] != "undefined") {
					vm.set(index, model[index]);
				};
			}
		});
		return vm;
	};
	populateModelFromVM = function(model, vm) {
		$.each(model, function(index, value){
			var val = "";
			if (index != "uid") {
				if (index == "oap_value_ids" || index == "offline_reasons" || index == "order_value_ids" || index == "quantities") {
					val = vm.get(index).join(",");
					model.set(index, val);
				} else if (typeof value != "function" && typeof value != "object" && typeof vm[index] != "undefined") {
					if (index.split("_")[index.split("_").length - 1] == "date") {
							val = kendo.toString(vm.get(index), "d");
							model[index] = val;
					} else if (index.split("_")[index.split("_").length - 2] == "date" && index.split("_")[index.split("_").length - 1] == "time") {
							val = kendo.toString(vm.get(index), "g");
							model[index] = val;
					} else if (index.split("_")[index.split("_").length - 1] == "time") {
							val = kendo.toString(vm.get(index), "h:mmtt");
							model[index] = val;
					} else {
						model.set(index, vm.get(index));
					}
				};
			};
		});
		return model;
	};
	launchModal = function(modalConfig) {
		// hide all other modals
		if (typeof modalArray == "undefined") {
			modalArray = [];
		};
		$.each(modalArray, function(index, value) {
			$("#" + modalArray[index].modalId).modal("hide");
		});
		// register this modal in the modalArray
		modalArray.push(modalConfig);
		loadTemplate("modal", modalConfig.modalTemplate);
		var mTemplate = kendo.template($("#" + modalConfig.modalTemplate).html(), {useWithBlock: false});
		$("body").append(mTemplate(modalConfig));
		$("#" + modalConfig.contentId).appendTo("#" + modalConfig.modalId + " .modal-body");
		// run modalOnload, if configured
		if (typeof modalConfig.modalOnload == "function") {
			modalConfig.modalOnload();
		};
		$("#" + modalConfig.modalId).modal("show");
		$(document).off('focusin.modal');
	};
	initWizardModal = function(vm) {
		vm.set("currentStep", 1);
		var uiConfig = vm.uiConfig().edit.modal;
		//var modalConfig = modalArray[modalArray.length - 1];
		var stepNext = function() {
			var vResp = vm.validateStep();
			if (vResp == true) {
				$("#" + uiConfig.modalId + " .modalAlert").hide();
				var currentStep = vm.get("currentStep") + 1;
				var nextStep = currentStep + 1;
				var backStep = currentStep - 1;
				if (!$("#" + uiConfig.contentId + " .step" + nextStep).length) {
					$("#" + uiConfig.modalId + " .nextButton").hide();
					$("#" + uiConfig.modalId + " .finishButton").show();
				}
				$("#" + uiConfig.modalId + " .backButton").show();
				var i = backStep;
				while (i > 0) {
					//console.log(i);
					$("#" + uiConfig.contentId + " .step" + i).hide();
					i = i -1;
				}
				$("#" + uiConfig.contentId + " .step" + currentStep).show();
				vm.set("currentStep", currentStep);
				vm.step();
			} else {
				$("#" + uiConfig.modalId + " .modalAlert").html(vResp).show();
			}
			return;
		};
		var stepBack = function() {
			$("#" + uiConfig.modalId + " .modalAlert").hide();
			var currentStep = vm.get("currentStep") - 1;
			var nextStep = currentStep + 1;
			var backStep = currentStep - 1;
			if (!$("#" + uiConfig.contentId + " .step" + backStep).length) {
				$("#" + uiConfig.modalId + " .backButton").hide();
			}
			$("#" + uiConfig.modalId + " .finishButton").hide();
			$("#" + uiConfig.modalId + " .nextButton").show();
			$("#" + uiConfig.contentId + " .step" + nextStep).hide();
			$("#" + uiConfig.contentId + " .step" + currentStep).show();
			vm.set("currentStep", currentStep);
			vm.step();
			return;
		};
		var finish = function() {
			var vResp = vm.validateStep();
			if (vResp == true) {
				$("#" + uiConfig.modalId + " .modalAlert").hide();
				vm.step();
			} else {
				$("#" + uiConfig.modalId + " .modalAlert").text(vResp).show();
			} 
			return;
		};
		$("#" + uiConfig.modalId + " .nextButton").on("click", stepNext);
		$("#" + uiConfig.modalId + " .backButton").on("click", stepBack);
		$("#" + uiConfig.modalId + " .finishButton").on("click", finish);
		$("#" + uiConfig.modalId + " .cancelButton").on("click", closeModal);
		$("#" + uiConfig.modalId + " .backButton").hide();
		$("#" + uiConfig.modalId + " .finishButton").hide();
		$("#" + uiConfig.modalId + " .nextButton").show();
		$("#" + uiConfig.contentId + " .step" + vm.get("currentStep")).show();
	};
	closeModal = function() {
		var modalConfig = modalArray.pop();
		var nextModalConfig = modalArray[modalArray.length - 1];
		$("#" + modalConfig.modalId).modal("hide");
		$("#" + modalConfig.contentId).remove();
		$("#" + modalConfig.modalId).remove();
		// show the next modal
		if (typeof nextModalConfig == "object") {
			$("#" + nextModalConfig.modalId).modal("show");
		}
	};
	toTitleCase = function(str) {
		return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
	};
	generateEvaluationCode = function() {
		var length = 8;
		var chars = "0123456789abcdefghijklmnopqrstuvwxyz";
		var result = "";
		for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
		return result;
	};
	loadTemplate = function(type, template) {
		var retVal = false;
		// check to see if content template is in the DOM, load if not
		if ($("#" + template).length == 0) {
			$.ajax({
				type: "GET",
				url: pathToTemplates + "/" + type + "s.cfm?template=" + template,
				async: false,
				success: function(response){
					$("body").append(response);
					retVal = true;						
				},
				error: function(jqXHR, textStatus, errorThrown){
					retVal = false;
					if (console.log) {
						//console.log("Error retrieving template: " + errorThrown);
					}
				}
			});
		} else if ($("#" + template).length > 0) {
			retVal = true;
		}
		return retVal;
	};
	toggleModalButtons = function(modalId, disable) {
		if ($("#" + modalId + " .modal-footer > button").length > 0) {
			$.each($("#" + modalId + " .modal-footer > button"), function(index, value) {
				value.disabled = disable;
			});
		}
	};
	getNextWorkshopDate = function(organizationId) {
		var ret = "";
		$.ajax({
			type: "GET",
			url: apiUrl + "?method=call",
			data: $.param({service: "procedure", sp: "getNextWorkshopDate", organization_id: typeof organizationId != "number" ? authUser.organizationId : organizationId}),
			dataType: "json",
			async: false,
			success: function(response){
				if (response.data.length > 0) {
					ret = response.data[0].next_workshop_date;
				} else {
					ret = false;
				}
			},
			error: function(jqXHR, textStatus, errorThrown){
				if (console.log) {
					//console.log(errorThrown);	
				};
				ret = false;
			}
		});	
		return ret;
	};
	getDuplicateEmails = function(email) {
		var ret = [];
		$.ajax({
			type: "GET",
			url: apiUrl + "?method=call",
			data: $.param({service: "procedure", sp: "getDuplicateEmails", email: email}),
			dataType: "json",
			async: false,
			success: function(response) {
				ret = response.data;		
			},
			error: function(jqXHR, textStatus, errorThrown) {
				if (console.log) {
					//console.log(errorThrown);	
				}
			}
		});
		return ret;
	};
	genCatSubcatItemMap = function(data) {
		var itemMap = {};
		var i = 0;
		$.each(data, function(index, value) {
			var category = data[index].category;
			var subcategory = data[index].subcategory;
			var itemObj = {};
			itemObj.index = i;
			$.each(data[index], function(idx, val) {
				itemObj[idx] = val;
			});
			if (typeof itemMap[category] == "undefined") {
				itemMap[category] = {}
			}
			if (typeof itemMap[category][subcategory] == "undefined") {
				itemMap[category][subcategory] = [];
			}
			itemMap[category][subcategory].push(itemObj);
			i = i + 1;
		});
		return itemMap;
	};
	andList = function(array) {
		var ret = "";
		$.each(array, function(index, value) {
			if (index == 0 || array.length <= 1) {
				ret = value;
			} else if (index + 1 < array.length) {
				ret = ret + ", " + value;
			} else {
				ret = ret + " and " + value;
			}
		});
		return ret;
	};
	acceptPA = function() {
		if (authUser.paId == 0) {
			var viewModel = getViewModel("pa");
			var model = populateModelFromVM(getModel("pa", 0), viewModel);
			model.organization_id = authUser.organizationId;
			model.accepted_by_id = authUser.userId;
			model.program_year = currentProgramYear;
			model.pa = viewModel.showPA1() ? $("#pa1").html() : $("#pa2").html();
			pas.add(model);
			pas.sync();
			pas.bind("change", function() {
				if (parseInt(pas.view()[0].pa_id, 10) > 0) {
					authUser.paId = parseInt(pas.view()[0].pa_id, 10);
					$.ajax({
						type: "GET",
						url: apiUrl + "?method=call",
						data: $.param({service: "function", fx: "setSessionProperty", name: "authUser.paId", value: authUser.paId}),
						dataType: "json",
						async: false,
						success: function(response) {
							if (console.log) {
								//console.log(response);	
							}
						},
						error: function(jqXHR, textStatus, errorThrown) {
							if (console.log) {
								//console.log(errorThrown);	
							}
						}
					});
				}
			})
			pas.read();
		}
		closeModal();
	}
	finishOAP = function() {
		if (authUser.oapId == 0) {
			var viewModel = getViewModel("oap");
			var model = populateModelFromVM(getModel("oap", 0), viewModel);
			model.organization_id = authUser.organizationId;
			model.created_by_id = authUser.userId;
			model.program_year = currentProgramYear;
			oaps.add(model);
			oaps.sync();
			oaps.bind("change", function() {
				if (parseInt(oaps.view()[0].oap_id, 10) > 0) {
					authUser.oapId = parseInt(oaps.view()[0].oap_id, 10);
					$.ajax({
						type: "GET",
						url: apiUrl + "?method=call",
						data: $.param({service: "function", fx: "setSessionProperty", name: "authUser.oapId", value: authUser.oapId}),
						dataType: "json",
						async: false,
						success: function(response) {
							if (console.log) {
								//console.log(response);	
							}	
						},
						error: function(jqXHR, textStatus, errorThrown) {
							if (console.log) {
								//console.log(errorThrown);	
							}
						}
					});
				}
			})
			oaps.read();
		}
		closeModal();
	};
	getDatasource = function(objType) {
		switch (objType) {
			case "account":
				return users;
			break;
			case "site":
				return sites;
			break;
			case "workshop":
				return workshops;
			break;
			case "user":
				return users;
			break;
			case "workshopVolunteer":
				return workshopVolunteers;
			break;
			case "volunteer":
				return volunteers;
			break;
			case "organization":
				return organizations;
			break;
			case "order":
				return orders;
			break;
			case "fund":
				return funds;
			break;
			case "evaluation":
				return evaluations;
			break;
			case "payment":
				return payments;
			break;
			case "oap":
				return oaps;
			break;
			case "pa":
				return pas;
			break;
		};	
	}
	getViewModel = function(objType) {
		switch (objType) {
			case "account":
				return accountViewModel;
			break;
			case "site":
				return siteViewModel;
			break;
			case "workshop":
				return workshopViewModel;
			break;
			case "user":
				return userViewModel;
			break;
			case "workshopVolunteer":
				return workshopVolunteerViewModel;
			break;
			case "volunteer":
				return volunteerViewModel;
			break;
			case "organization":
				return organizationViewModel;
			break;
			case "order":
				return orderViewModel;
			break;
			case "fund":
				return fundViewModel;
			break;
			case "evaluation":
				return evaluationViewModel;
			break;
			case "payment":
				return paymentViewModel;
			break;
			case "oap":
				return oapViewModel;
			break;
			case "pa":
				return paViewModel;
			break;
		};
	}
	getModel = function(objType, id) {
		var ds = getDatasource(objType);
		var model;
		switch (objType) {
			case "account":
				model = id == 0 ? new User : ds.get(id);
			break;
			case "site":
				model = id == 0 ? new Site : ds.get(id);
			break;
			case "workshop":
				model = id == 0 ? new Workshop : ds.get(id);
			break;
			case "user":
				model = id == 0 ? new User : ds.get(id);
			break;
			case "workshopVolunteer":
				model = id == 0 ? new WorkshopVolunteer : ds.get(id);
			break;
			case "volunteer":
				model = id == 0 ? new Volunteer : ds.get(id);
			break;
			case "organization":
				model = id == 0 ? new Organization : ds.get(id);
			break;
			case "order":
				model = id == 0 ? new Order : ds.get(id);
			break;
			case "fund":
				model = id == 0 ? new Fund : ds.get(id);
			break;
			case "evaluation":
				model = id == 0 ? new Evaluation : ds.get(id);
			break;
			case "payment":
				model = id == 0 ? new Payment : ds.get(id);
			break;
			case "oap":
				model = id == 0 ? new OAP : ds.get(id);
			break;
			case "pa":
				model = id == 0 ? new PA : ds.get(id);
			break;
		};
		return model;
	}
	calculateTimelineProgress = function() {
		var currentYears = currentProgramYear.split("-");
		var year1 = currentYears[0];
		var year2 = currentYears[1];

		var startDate = new Date(year1, 9, 0);
		var phase2Date = new Date(year2, 0, 0);
		var phase3Date = new Date(year2, 2, 2);
		var endDate = new Date(year2, 7, 29);

		// get today's date
		var today = new Date();
		//var daysIntoSeason = Date.daysBetween(startDate, today);
		var daysIntoPhase = 0;
		var daysInPhase = 0;
		var previousPhases = 0;
		
		if (today < phase2Date) {
			daysInPhase = Date.daysBetween(startDate, phase2Date);
			daysIntoPhase = Date.daysBetween(startDate, today);
		} else if (today < phase3Date) {
			daysInPhase = Date.daysBetween(phase2Date, phase3Date);
			daysIntoPhase = Date.daysBetween(phase2Date, today);
			previousPhases = 1;
		} else {
			daysInPhase = Date.daysBetween(phase3Date, endDate);
			daysIntoPhase = Date.daysBetween(phase3Date, today);
			previousPhases = 2;
		}
		var seasonProgress = .33 * previousPhases;
		var phaseProgress = daysIntoPhase / daysInPhase;
		var overallProgress = seasonProgress + phaseProgress * .33;
		// the subtraction adjustment is half the width of the indictaor
		var overallProgressPx = overallProgress * 960 - 4;
		return overallProgressPx;
	}
	Date.daysBetween = function (date1, date2) {
		//Get 1 day in milliseconds
		var one_day = 1000 * 60 * 60 * 24;

		// Convert both dates to milliseconds
		var date1_ms = date1.getTime();
		var date2_ms = date2.getTime();

		// Calculate the difference in milliseconds
		var difference_ms = date2_ms - date1_ms;

		// Convert back to days and return
		return Math.round(difference_ms / one_day);
	}
	/***************************************************************
	$(document).on("submit", "form", function(e) {
		e.preventDefault();
	});
	
	_syncDatasource = function(datasource) {
		if (datasource == workshops) {
			//console.log("syncing workshops");
			workshops.sync();
			//workshops.read();
		} else {
			//console.log("syncDatasource called");
			datasource.sync();
			setTimeout(function() {
				datasource.read();
				if (datasource == users) {
					organizers.read();
					managers.read();
				};
			}, 1000);
		}
		return;
	};
	_populateVMFromModel = function(objType, id) {
		switch (objType) {
			case "site":
				var vm = siteViewModel;
				var model = id == 0 ? new Site : sites.get(id);
			break;
			case "workshop":
				var vm = workshopViewModel;
				var model = id == 0 ? new Workshop : workshops.get(id);
			break;
			case "user":
				var vm = userViewModel;
				var model = id == 0 ? new User : users.get(id);
			break;
			case "workshopVolunteer":
				var vm = workshopVolunteerViewModel;
				var model = id == 0 ? new WorkshopVolunteer : workshopVolunteers.get(id);
			break;
			case "volunteer":
				var vm = volunteerViewModel;
				var model = id == 0 ? new Volunteer : volunteers.get(id);
			break;
			case "organization":
				var vm = organizationViewModel;
				var model = id == 0 ? new Organization : organizations.get(id);
			break;
			case "order":
				var vm = orderViewModel;
				var model = id == 0 ? new Order : orders.get(id);
			break;
			case "fund":
				var vm = fundViewModel;
				var model = id == 0 ? new Fund : funds.get(id);
			break;
			case "evaluation":
				var vm = evaluationViewModel;
				var model = id == 0 ? new Evaluation : evaluations.get(id);
			break;
			case "payment":
				var vm = paymentViewModel;
				var model = id == 0 ? new Payment : payments.get(id);
			break;
			case "pa":
				var vm = paViewModel;
				var model = id == 0 ? new PA : pas.get(id);
			break;
			case "oap":
				var vm = oapViewModel;
				var model = id == 0 ? new OAP : oaps.get(id);
			break;
		};
		$.each(vm, function(index, value){
			if (index != "uid") {
				// set all defaults that can't be set in model, convert model data to view model data where necessary (e.g. convert model lists to view model arrays)
				if (index == "oap_value_ids" || index == "offline_reasons" || index == "order_value_ids" || index == "quantities") {
					vm.set(index, id == 0 || model[index] == "" ? [] : model[index].split(","));
				} else if (index == "organization_id") {
					vm.set(index, id == 0 ? authUser.organizationId : model.organization_id);
				} else if (index == "ordered_by_id") {
					vm.set(index, id == 0 ? authUser.userId : model.ordered_by_id);
				} else if (index == "program_year") {
					vm.set("program_year", id == 0 ? currentProgramYear : model.program_year);
				} else if (index == "evaluation_code") {
					vm.set("evaluation_code", id == 0 ? generateEvaluationCode() : model.evaluation_code);
				} else if (typeof model.fields[index] != "undefined" && model.fields[index].type == "boolean") {
					vm.set(index, model[index] == 1 ? true : false);
				} else if (typeof value != "function" && typeof value != "object" && typeof model[index] != "undefined") {
					vm.set(index, model[index]);
				};
			}
		});
		return vm;
	};
	_populateModelFromVM = function(objType, id) {
		switch (objType) {
			case "site":
				var vm = siteViewModel;
				var model = id == 0 ? new Site : sites.get(id);
			break;
			case "workshop":
				var vm = workshopViewModel;
				var model = id == 0 ? new Workshop : workshops.get(id);
			break;
			case "user":
				var vm = userViewModel;
				var model = id == 0 ? new User : users.get(id);
			break;
			case "workshopVolunteer":
				var vm = workshopVolunteerViewModel;
				var model = id == 0 ? new WorkshopVolunteer : workshopVolunteers.get(id);
			break;
			case "organization":
				var vm = organizationViewModel;
				var model = id == 0 ? new Organization : organizations.get(id);
			break;
			case "order":
				var vm = orderViewModel;
				var model = id == 0 ? new Order : orders.get(id);
			break;
			case "fund":
				var vm = fundViewModel;
				var model = id == 0 ? new Fund : funds.get(id);
			break;
			case "evaluation":
				var vm = evaluationViewModel;
				var model = id == 0 ? new Evaluation : evaluations.get(id);
			break;
			case "payment":
				var vm = paymentViewModel;
				var model = id == 0 ? new Payment : payments.get(id);
			break;
			case "oap":
				var vm = oapViewModel;
				var model = id == 0 ? new OAP : oaps.get(id);
			break;
		};
		$.each(model, function(index, value){
			if (index != "uid") {
				if (index == "oap_value_ids" || index == "offline_reasons" || index == "order_value_ids" || index == "quantities") {
					model[index] = vm.get(index).join(",");
				} else if (typeof value != "function" && typeof value != "object" && typeof vm[index] != "undefined") {
					if (index.split("_")[index.split("_").length - 1] == "date") {
						model[index] = kendo.toString(vm.get(index), "d");
					} else if (index.split("_")[index.split("_").length - 2] == "date" && index.split("_")[index.split("_").length - 1] == "time") {
						model[index] = kendo.toString(vm.get(index), "g");
					} else if (index.split("_")[index.split("_").length - 1] == "time") {
						model[index] = kendo.toString(vm.get(index), "h:mmtt");
					} else {
						model[index] = vm.get(index);
					}
				};
			};
		});
		return model;		
	};
	***************************************************************/
})
